]> dgit.raspbian.org Git - gnome-shell.git/commitdiff
Add support for asynchronous search providers
authorPhilippe Normand <philn@igalia.com>
Sun, 24 Jul 2011 10:29:36 +0000 (12:29 +0200)
committerJasper St. Pierre <jstpierre@mecheye.net>
Tue, 30 Aug 2011 15:55:28 +0000 (11:55 -0400)
Some search providers may want to change their results, or may not
want to block on an external service to get their results (DBus, etc.)
Set up an infrastructure to allow search providers to add their search
results at a later time.

Based on a patch by Jasper St. Pierre and Seif Lotfy.

https://bugzilla.gnome.org/show_bug.cgi?id=655220

js/ui/search.js
js/ui/searchDisplay.js
js/ui/viewSelector.js

index 47cb0e6de227d3ae427e09c1d1ccc0f5376c3f16..5b6a2c28fd29d2bc9b6600fd668eb06ea8a66b3c 100644 (file)
@@ -112,6 +112,43 @@ function SearchProvider(title) {
 SearchProvider.prototype = {
     _init: function(title) {
         this.title = title;
+        this.searchSystem = null;
+        this.searchAsync  = false;
+    },
+
+    _asyncCancelled: function() {
+    },
+
+    startAsync: function() {
+        this.searchAsync = true;
+    },
+
+    tryCancelAsync: function() {
+        if (!this.searchAsync)
+            return;
+        this._asyncCancelled();
+        this.searchAsync = false;
+    },
+
+    /**
+     * addItems:
+     * @items: an array of result identifier strings representing
+     * items which match the last given search terms.
+     *
+     * This should be used for something that requires a bit more
+     * logic; it's designed to be an asyncronous way to add a result
+     * to the current search.
+     */
+    addItems: function(items) {
+        if (!this.searchSystem)
+            throw new Error('Search provider not registered');
+
+        if (!items.length)
+            return;
+
+        this.tryCancelAsync();
+
+        this.searchSystem.addProviderItems(this, items);
     },
 
     /**
@@ -315,6 +352,7 @@ SearchSystem.prototype = {
     },
 
     registerProvider: function (provider) {
+        provider.searchSystem = this;
         this._providers.push(provider);
     },
 
@@ -331,12 +369,23 @@ SearchSystem.prototype = {
         this._previousResults = [];
     },
 
+    addProviderItems: function(provider, items) {
+        this.emit('search-updated', provider, items);
+    },
+
     updateSearch: function(searchString) {
         searchString = searchString.replace(/^\s+/g, '').replace(/\s+$/g, '');
         if (searchString == '')
-            return [];
+            return;
 
         let terms = searchString.split(/\s+/);
+        this.updateSearchResults(terms);
+    },
+
+    updateSearchResults: function(terms) {
+        if (!terms)
+            return;
+
         let isSubSearch = terms.length == this._previousTerms.length;
         if (isSubSearch) {
             for (let i = 0; i < terms.length; i++) {
@@ -349,12 +398,12 @@ SearchSystem.prototype = {
 
         let results = [];
         if (isSubSearch) {
-            for (let i = 0; i < this._previousResults.length; i++) {
+            for (let i = 0; i < this._providers.length; i++) {
                 let [provider, previousResults] = this._previousResults[i];
+                provider.tryCancelAsync();
                 try {
                     let providerResults = provider.getSubsearchResultSet(previousResults, terms);
-                    if (providerResults.length > 0)
-                        results.push([provider, providerResults]);
+                    results.push([provider, providerResults]);
                 } catch (error) {
                     global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
                 }
@@ -362,10 +411,10 @@ SearchSystem.prototype = {
         } else {
             for (let i = 0; i < this._providers.length; i++) {
                 let provider = this._providers[i];
+                provider.tryCancelAsync();
                 try {
                     let providerResults = provider.getInitialResultSet(terms);
-                    if (providerResults.length > 0)
-                        results.push([provider, providerResults]);
+                    results.push([provider, providerResults]);
                 } catch (error) {
                     global.log ('A ' + error.name + ' has occured in ' + provider.title + ': ' + error.message);
                 }
@@ -374,8 +423,7 @@ SearchSystem.prototype = {
 
         this._previousTerms = terms;
         this._previousResults = results;
-
-        return results;
-    }
+        this.emit('search-completed', results);
+    },
 };
 Signals.addSignalMethods(SearchSystem.prototype);
index 580f410be3ae6bcf16a33ba558a6e223b4d43a00..04ef64cdfbd7959b97dacb7e8217c91336b6ff22 100644 (file)
@@ -189,6 +189,8 @@ function SearchResults(searchSystem, openSearchSystem) {
 SearchResults.prototype = {
     _init: function(searchSystem, openSearchSystem) {
         this._searchSystem = searchSystem;
+        this._searchSystem.connect('search-updated', Lang.bind(this, this._updateCurrentResults));
+        this._searchSystem.connect('search-completed', Lang.bind(this, this._updateResults));
         this._openSearchSystem = openSearchSystem;
 
         this.actor = new St.BoxLayout({ name: 'searchResults',
@@ -223,9 +225,11 @@ SearchResults.prototype = {
         this._selectedProvider = -1;
         this._providers = this._searchSystem.getProviders();
         this._providerMeta = [];
-        for (let i = 0; i < this._providers.length; i++)
+        this._providerMetaResults = {};
+        for (let i = 0; i < this._providers.length; i++) {
             this.createProviderMeta(this._providers[i]);
-
+            this._providerMetaResults[this.providers[i].title] = [];
+        }
         this._searchProvidersBox = new St.BoxLayout({ style_class: 'search-providers-box' });
         this.actor.add(this._searchProvidersBox);
 
@@ -305,6 +309,12 @@ SearchResults.prototype = {
         }
     },
 
+    _clearDisplayForProvider: function(index) {
+        let meta = this._providerMeta[index];
+        meta.resultDisplay.clear();
+        meta.actor.hide();
+    },
+
     reset: function() {
         this._searchSystem.reset();
         this._statusText.hide();
@@ -319,15 +329,24 @@ SearchResults.prototype = {
         this._statusText.show();
     },
 
+    doSearch: function (searchString) {
+        this._searchSystem.updateSearch(searchString);
+    },
+
     _metaForProvider: function(provider) {
         return this._providerMeta[this._providers.indexOf(provider)];
     },
 
-    updateSearch: function (searchString) {
-        let results = this._searchSystem.updateSearch(searchString);
-
-        this._clearDisplay();
+    _updateCurrentResults: function(searchSystem, provider, results) {
+        let terms = searchSystem.getTerms();
+        let meta = this._metaForProvider(provider);
+        meta.resultDisplay.clear();
+        meta.actor.show();
+        meta.resultDisplay.renderResults(results, terms);
+        return true;
+    },
 
+    _updateResults: function(searchSystem, results) {
         if (results.length == 0) {
             this._statusText.set_text(_("No matching results."));
             this._statusText.show();
@@ -337,7 +356,7 @@ SearchResults.prototype = {
             this._statusText.hide();
         }
 
-        let terms = this._searchSystem.getTerms();
+        let terms = searchSystem.getTerms();
         this._openSearchSystem.setSearchTerms(terms);
 
         // To avoid CSS transitions causing flickering
@@ -349,9 +368,15 @@ SearchResults.prototype = {
 
         for (let i = 0; i < results.length; i++) {
             let [provider, providerResults] = results[i];
-            let meta = this._metaForProvider(provider);
-            meta.actor.show();
-            meta.resultDisplay.renderResults(providerResults, terms);
+            if (providerResults.length == 0) {
+                this._clearDisplayForProvider(i);
+            } else {
+                this._providerMetaResults[provider.title] = providerResults;
+                this._clearDisplayForProvider(i);
+                let meta = this._metaForProvider(provider);
+                meta.actor.show();
+                meta.resultDisplay.renderResults(providerResults, terms);
+            }
         }
 
         if (this._selectedOpenSearchButton == -1)
index 53b349c778ccb00ed4ae6c36ef2dc377b74c5e05..b33139f5767436fd38563c6417cbd6b7a8d22c33 100644 (file)
@@ -297,7 +297,7 @@ SearchTab.prototype = {
     _doSearch: function () {
         this._searchTimeoutId = 0;
         let text = this._text.get_text().replace(/^\s+/g, '').replace(/\s+$/g, '');
-        this._searchResults.updateSearch(text);
+        this._searchResults.doSearch(text);
 
         return false;
     }